<!--
  右键菜单组件
  支持动态菜单项、键盘导航、智能定位
  @author LYC
  @date 2025-09-13
-->

<template>
  <Teleport to="body">
    <Transition name="context-menu" appear>
      <div
        v-if="contextMenu.state.visible"
        ref="menuRef"
        class="context-menu"
        :style="{
          left: contextMenu.state.position.x + 'px',
          top: contextMenu.state.position.y + 'px'
        }"
        @click.stop
        @contextmenu.prevent
      >
        <div class="context-menu-content">
          <template v-for="(item, index) in menuItems" :key="item.id">
            <!-- 分割线 -->
            <div v-if="item.divider" class="context-menu-divider" />

            <!-- 菜单项 -->
            <div
              v-else
              class="context-menu-item"
              :class="{
                'context-menu-item--disabled': item.disabled,
                'context-menu-item--focused': focusedIndex === index
              }"
              @click="handleItemClick(item)"
              @mouseenter="focusedIndex = index"
            >
              <!-- 图标 -->
              <span v-if="item.icon" class="context-menu-item__icon">
                <component :is="item.icon" :size="16" />
              </span>

              <!-- 标签 -->
              <span class="context-menu-item__label">
                {{ item.label }}
              </span>

              <!-- 快捷键 -->
              <span v-if="item.shortcut" class="context-menu-item__shortcut">
                {{ item.shortcut }}
              </span>
            </div>
          </template>
        </div>
      </div>
    </Transition>
  </Teleport>
</template>

<script lang="ts" setup>
import { ref, computed, onMounted, onUnmounted, watch, nextTick } from 'vue'
import { useGlobalContextMenu } from '@/composables/useContextMenu'
import { useContextMenuActions } from '@/composables/useContextMenuActions'

// 组合式API
const contextMenu = useGlobalContextMenu()
const contextMenuActions = useContextMenuActions()

// 响应式数据
const menuRef = contextMenu.menuRef
const focusedIndex = ref(-1)

// 计算属性
const menuItems = computed(() => {
  const { targetMessage } = contextMenu.state
  if (!targetMessage) return []

  return contextMenuActions.getContextMenuActions(targetMessage)
})

// 方法
const handleItemClick = async (item: any) => {
  if (item.disabled) return

  try {
    await contextMenu.handleMenuItemClick(item)
    focusedIndex.value = -1
  } catch (error) {
    console.error('Menu item action failed:', error)
  }
}

const handleKeydown = (event: KeyboardEvent): void => {
  if (!contextMenu.state.visible) return

  switch (event.key) {
    case 'Escape':
      contextMenu.hideContextMenu()
      break

    case 'ArrowUp':
      event.preventDefault()
      moveFocus(-1)
      break

    case 'ArrowDown':
      event.preventDefault()
      moveFocus(1)
      break

    case 'Enter':
      event.preventDefault()
      if (focusedIndex.value >= 0) {
        const item = menuItems.value[focusedIndex.value]
        if (item && !item.disabled && !item.divider) {
          handleItemClick(item)
        }
      }
      break
  }
}

const moveFocus = (direction: number): void => {
  const items = menuItems.value.filter((item) => !item.divider && !item.disabled)
  if (items.length === 0) return

  let newIndex = focusedIndex.value + direction

  // 循环导航
  if (newIndex >= items.length) {
    newIndex = 0
  } else if (newIndex < 0) {
    newIndex = items.length - 1
  }

  // 找到实际的索引（跳过分割线和禁用项）
  let actualIndex = 0
  let validItemCount = 0

  for (let i = 0; i < menuItems.value.length; i++) {
    const item = menuItems.value[i]
    if (!item.divider && !item.disabled) {
      if (validItemCount === newIndex) {
        actualIndex = i
        break
      }
      validItemCount++
    }
  }

  focusedIndex.value = actualIndex
}

const handleClickOutside = (event: MouseEvent): void => {
  contextMenu.handleClickOutside(event)
}

// 监听菜单显示状态
watch(
  () => contextMenu.state.visible,
  (visible) => {
    if (visible) {
      focusedIndex.value = -1
      nextTick(() => {
        // 调整菜单位置
        contextMenu.adjustMenuPosition?.()
      })
    }
  }
)

// 生命周期
onMounted(() => {
  document.addEventListener('keydown', handleKeydown)
  document.addEventListener('click', handleClickOutside)
})

onUnmounted(() => {
  document.removeEventListener('keydown', handleKeydown)
  document.removeEventListener('click', handleClickOutside)
})
</script>

<style scoped>
/* 右键菜单容器 */
.context-menu {
  position: fixed;
  z-index: 9999;
  min-width: 200px;
  background: var(--theme-bg-primary);
  border: 1px solid var(--theme-border);
  border-radius: var(--border-radius-medium);
  box-shadow: var(--shadow-large);
  user-select: none;
  overflow: hidden;
}

/* 菜单内容 */
.context-menu-content {
  padding: var(--spacing-mini) 0;
}

/* 菜单项 */
.context-menu-item {
  display: flex;
  align-items: center;
  padding: var(--spacing-small) var(--spacing-medium);
  cursor: pointer;
  transition: background-color var(--transition-duration) var(--transition-timing-function);
  font-size: var(--font-size-base);
  line-height: var(--line-height-tight);
}

.context-menu-item:hover,
.context-menu-item--focused {
  background-color: var(--theme-bg-secondary);
}

.context-menu-item--disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.context-menu-item--disabled:hover {
  background-color: transparent;
}

/* 菜单项图标 */
.context-menu-item__icon {
  width: 20px;
  height: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-right: var(--spacing-small);
  font-size: 14px;
  flex-shrink: 0;
}

/* 菜单项标签 */
.context-menu-item__label {
  flex: 1;
  color: var(--theme-text-primary);
}

.context-menu-item--disabled .context-menu-item__label {
  color: var(--theme-text-tertiary);
  opacity: 0.6;
}

/* 菜单项快捷键 */
.context-menu-item__shortcut {
  margin-left: var(--spacing-medium);
  font-size: var(--font-size-small);
  color: var(--theme-text-tertiary);
  flex-shrink: 0;
}

/* 分割线 */
.context-menu-divider {
  height: 1px;
  background-color: var(--theme-border-light);
  margin: var(--spacing-mini) 0;
}

/* 动画效果 */
.context-menu-enter-active,
.context-menu-leave-active {
  transition: all 0.15s ease-out;
}

.context-menu-enter-from {
  opacity: 0;
  transform: scale(0.95) translateY(-5px);
}

.context-menu-leave-to {
  opacity: 0;
  transform: scale(0.95) translateY(-5px);
}

/* 深色主题适配 */
[data-theme='dark'] .context-menu {
  background: var(--theme-bg-secondary);
  border-color: var(--theme-border);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
}

[data-theme='dark'] .context-menu-item:hover,
[data-theme='dark'] .context-menu-item--focused {
  background-color: var(--theme-bg-tertiary);
}

[data-theme='dark'] .context-menu-item__label {
  color: var(--theme-text-primary);
}

[data-theme='dark'] .context-menu-item__shortcut {
  color: var(--theme-text-tertiary);
}

[data-theme='dark'] .context-menu-divider {
  background-color: var(--theme-border);
}

/* 响应式设计 */
@media (max-width: 768px) {
  .context-menu {
    min-width: 180px;
  }

  .context-menu-item {
    padding: var(--spacing-base) var(--spacing-medium);
  }

  .context-menu-item__shortcut {
    display: none; /* 移动端隐藏快捷键 */
  }
}
</style>
